home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1994 David I. Bell
- * Permission is granted to use, distribute, or modify this source,
- * provided that this copyright notice remains intact.
- *
- * Modified for the Amiga by Steve Leblanc, Oct 1995
- *
- * Global and local symbol routines.
- */
-
- #include "calc.h"
- #include "token.h"
- #include "symbol.h"
- #include "string.h"
- #include "opcodes.h"
- #include "func.h"
-
- #define HASHSIZE 37 /* size of hash table */
-
-
- static int filescope; /* file scope level for static variables */
- static int funcscope; /* function scope level for static variables */
- static STRINGHEAD localnames; /* list of local variable names */
- static STRINGHEAD globalnames; /* list of global variable names */
- static STRINGHEAD paramnames; /* list of parameter variable names */
- static GLOBAL *globalhash[HASHSIZE]; /* hash table for globals */
-
- static void fitprint MATH_PROTO((NUMBER *num, long digits, long width));
- static void unscope MATH_PROTO((void));
-
-
- /*
- * Hash a symbol name so we can find it in the hash table.
- * Args are the symbol name and the symbol name size.
- */
- #define HASHSYM(n, s) ((unsigned)((n)[0]*123 + (n)[s-1]*135 + (s)*157) % HASHSIZE)
-
-
- /*
- * Initialize the global symbol table.
- */
- void
- initglobals()
- {
- int i; /* index counter */
-
- for (i = 0; i < HASHSIZE; i++)
- globalhash[i] = NULL;
- initstr(&globalnames);
- filescope = SCOPE_STATIC;
- funcscope = 0;
- }
-
-
- /*
- * Define a possibly new global variable which may or may not be static.
- * If it did not already exist, it is created with a value of zero.
- * The address of the global symbol structure is returned.
- */
- GLOBAL *
- addglobal(name, isstatic)
- char *name; /* name of global variable */
- BOOL isstatic; /* TRUE if symbol is static */
- {
- GLOBAL *sp; /* current symbol pointer */
- GLOBAL **hp; /* hash table head address */
- long len; /* length of string */
- int newfilescope; /* file scope being looked for */
- int newfuncscope; /* function scope being looked for */
-
- newfilescope = SCOPE_GLOBAL;
- newfuncscope = 0;
- if (isstatic) {
- newfilescope = filescope;
- newfuncscope = funcscope;
- }
- len = strlen(name);
- if (len <= 0)
- return NULL;
- hp = &globalhash[HASHSYM(name, len)];
- for (sp = *hp; sp; sp = sp->g_next) {
- if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0)
- && (sp->g_filescope == newfilescope)
- && (sp->g_funcscope == newfuncscope))
- return sp;
- }
- sp = (GLOBAL *) malloc(sizeof(GLOBAL));
- if (sp == NULL)
- return sp;
- sp->g_name = addstr(&globalnames, name);
- sp->g_len = len;
- sp->g_filescope = newfilescope;
- sp->g_funcscope = newfuncscope;
- sp->g_value.v_num = qlink(&_qzero_);
- sp->g_value.v_type = V_NUM;
- sp->g_next = *hp;
- *hp = sp;
- return sp;
- }
-
-
- /*
- * Look up the name of a global variable and return its address.
- * Since the same variable may appear in different scopes, we search
- * for the one with the highest function scope value within the current
- * file scope level (or which is global). Returns NULL if the symbol
- * was not found.
- */
- GLOBAL *
- findglobal(name)
- char *name; /* name of global variable */
- {
- GLOBAL *sp; /* current symbol pointer */
- GLOBAL *bestsp; /* found symbol with highest scope */
- long len; /* length of string */
-
- bestsp = NULL;
- len = strlen(name);
- for (sp = globalhash[HASHSYM(name, len)]; sp; sp = sp->g_next) {
- if ((sp->g_len != len) || strcmp(sp->g_name, name))
- continue;
- if (sp->g_filescope == SCOPE_GLOBAL) {
- if (bestsp == NULL)
- bestsp = sp;
- continue;
- }
- if (sp->g_filescope != filescope)
- continue;
- if ((bestsp == NULL) || (sp->g_funcscope > bestsp->g_funcscope))
- bestsp = sp;
- }
- return bestsp;
- }
-
-
- /*
- * Return the name of a global variable given its address.
- */
- char *
- globalname(sp)
- GLOBAL *sp; /* address of global pointer */
- {
- if (sp)
- return sp->g_name;
- return "";
- }
-
-
- /*
- * Show the value of all global variables, typing only the head and
- * tail of very large numbers. Only truly global symbols are shown.
- */
- void
- showglobals()
- {
- GLOBAL **hp; /* hash table head address */
- register GLOBAL *sp; /* current global symbol pointer */
- long count; /* number of global variables shown */
- NUMBER *num, *den;
- long digits;
-
- count = 0;
- for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
- for (sp = *hp; sp; sp = sp->g_next) {
- if (sp->g_value.v_type != V_NUM)
- continue;
- if (sp->g_filescope != SCOPE_GLOBAL)
- continue;
- if (count++ == 0) {
- printf("\nName Digits Value\n");
- printf( "---- ------ -----\n");
- }
- printf("%-8s ", sp->g_name);
- num = qnum(sp->g_value.v_num);
- digits = qdigits(num);
- printf("%-7ld ", digits);
- fitprint(num, digits, 60L);
- qfree(num);
- if (!qisint(sp->g_value.v_num)) {
- den = qden(sp->g_value.v_num);
- digits = qdigits(den);
- printf("\n %-6ld /", digits);
- fitprint(den, digits, 60L);
- qfree(den);
- }
- printf("\n");
- }
- }
- printf(count ? "\n" : "No global variables defined.\n");
- }
-
-
- /*
- * Print an integer which is guaranteed to fit in the specified number
- * of columns, using imbedded '...' characters if it is too large.
- */
- static void
- fitprint(num, digits, width)
- NUMBER *num; /* number to print */
- long digits, width;
- {
- long show, used;
- NUMBER *p, *t, *div, *val;
-
- if (digits <= width) {
- qprintf("%r", num);
- return;
- }
- show = (width / 2) - 2;
- t = itoq(10L);
- p = itoq((long) (digits - show));
- div = qpowi(t, p);
- val = qquo(num, div);
- qprintf("%r...", val);
- qfree(p);
- qfree(div);
- qfree(val);
- p = itoq(show);
- div = qpowi(t, p);
- val = qmod(num, div);
- used = qdigits(val);
- while (used++ < show) printf("0");
- qprintf("%r", val);
- qfree(p);
- qfree(div);
- qfree(val);
- qfree(t);
- }
-
-
- /*
- * Write all normal global variables to an output file.
- * Note: Currently only simple types are saved.
- * Returns nonzero on error.
- */
- int
- writeglobals(name)
- char *name;
- {
- FILE *fp;
- GLOBAL **hp; /* hash table head address */
- register GLOBAL *sp; /* current global symbol pointer */
- int savemode; /* saved output mode */
-
- /* AMIGA MOD: using fopen rather that f_open */
- fp = fopen(name, "w");
- if (fp == NULL)
- return 1;
- math_setfp(fp);
- for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
- for (sp = *hp; sp; sp = sp->g_next) {
- switch (sp->g_value.v_type) {
- case V_NUM:
- case V_COM:
- case V_STR:
- break;
- default:
- continue;
- }
- math_fmt("%s = ", sp->g_name);
- savemode = math_setmode(MODE_HEX);
- printvalue(&sp->g_value, PRINT_UNAMBIG);
- math_setmode(savemode);
- math_str(";\n");
- }
- }
- math_setfp(stdout);
- if (fclose(fp))
- return 1;
- return 0;
- }
-
-
- /*
- * Reset the file and function scope levels back to the original values.
- * This is called on errors to forget any static variables which were being
- * defined.
- */
- void
- resetscopes()
- {
- filescope = SCOPE_STATIC;
- funcscope = 0;
- unscope();
- }
-
-
- /*
- * Enter a new file scope level so that newly defined static variables
- * will have the appropriate scope, and so that previously defined static
- * variables will temporarily be unaccessible. This should only be called
- * when the function scope level is zero.
- */
- void
- enterfilescope()
- {
- filescope++;
- funcscope = 0;
- }
-
-
- /*
- * Exit from a file scope level. This deletes from the global symbol table
- * all of the static variables that were defined within this file scope level.
- * The function scope level is also reset to zero.
- */
- void
- exitfilescope()
- {
- if (filescope > SCOPE_STATIC)
- filescope--;
- funcscope = 0;
- unscope();
- }
-
-
- /*
- * Enter a new function scope level within the current file scope level.
- * This allows newly defined static variables to override previously defined
- * static variables in the same file scope level.
- */
- void
- enterfuncscope()
- {
- funcscope++;
- }
-
-
- /*
- * Exit from a function scope level. This deletes static symbols which were
- * defined within the current function scope level, and makes previously
- * defined symbols with the same name within the same file scope level
- * accessible again.
- */
- void
- exitfuncscope()
- {
- if (funcscope > 0)
- funcscope--;
- unscope();
- }
-
-
- /*
- * Remove all the symbols from the global symbol table which have file or
- * function scopes larger than the current scope levels. Their memory
- * remains allocated since their values still actually exist.
- */
- static void
- unscope()
- {
- GLOBAL **hp; /* hash table head address */
- register GLOBAL *sp; /* current global symbol pointer */
- GLOBAL *prevsp; /* previous kept symbol pointer */
-
- for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
- prevsp = NULL;
- for (sp = *hp; sp; sp = sp->g_next) {
- if ((sp->g_filescope == SCOPE_GLOBAL) ||
- (sp->g_filescope < filescope) ||
- ((sp->g_filescope == filescope) &&
- (sp->g_funcscope <= funcscope)))
- {
- prevsp = sp;
- continue;
- }
-
- /*
- * This symbol needs removing.
- */
- if (prevsp)
- prevsp->g_next = sp->g_next;
- else
- *hp = sp->g_next;
- }
- }
- }
-
-
- /*
- * Initialize the local and parameter symbol table information.
- */
- void
- initlocals()
- {
- initstr(&localnames);
- initstr(¶mnames);
- curfunc->f_localcount = 0;
- curfunc->f_paramcount = 0;
- }
-
-
- /*
- * Add a possibly new local variable definition.
- * Returns the index of the variable into the local symbol table.
- * Minus one indicates the symbol could not be added.
- */
- long
- addlocal(name)
- char *name; /* name of local variable */
- {
- long index; /* current symbol index */
-
- index = findstr(&localnames, name);
- if (index >= 0)
- return index;
- index = localnames.h_count;
- (void) addstr(&localnames, name);
- curfunc->f_localcount++;
- return index;
- }
-
-
- /*
- * Find a local variable name and return its index.
- * Returns minus one if the variable name is not defined.
- */
- long
- findlocal(name)
- char *name; /* name of local variable */
- {
- return findstr(&localnames, name);
- }
-
-
- /*
- * Return the name of a local variable.
- */
- char *
- localname(n)
- long n;
- {
- return namestr(&localnames, n);
- }
-
-
- /*
- * Add a possibly new parameter variable definition.
- * Returns the index of the variable into the parameter symbol table.
- * Minus one indicates the symbol could not be added.
- */
- long
- addparam(name)
- char *name; /* name of parameter variable */
- {
- long index; /* current symbol index */
-
- index = findstr(¶mnames, name);
- if (index >= 0)
- return index;
- index = paramnames.h_count;
- (void) addstr(¶mnames, name);
- curfunc->f_paramcount++;
- return index;
- }
-
-
- /*
- * Find a parameter variable name and return its index.
- * Returns minus one if the variable name is not defined.
- */
- long
- findparam(name)
- char *name; /* name of parameter variable */
- {
- return findstr(¶mnames, name);
- }
-
-
- /*
- * Return the name of a parameter variable.
- */
- char *
- paramname(n)
- long n;
- {
- return namestr(¶mnames, n);
- }
-
-
- /*
- * Return the type of a variable name.
- * This is either local, parameter, global, static, or undefined.
- */
- int
- symboltype(name)
- char *name; /* variable name to find */
- {
- GLOBAL *sp;
-
- if (findlocal(name) >= 0)
- return SYM_LOCAL;
- if (findparam(name) >= 0)
- return SYM_PARAM;
- sp = findglobal(name);
- if (sp) {
- if (sp->g_filescope == SCOPE_GLOBAL)
- return SYM_GLOBAL;
- return SYM_STATIC;
- }
- return SYM_UNDEFINED;
- }
-
- /* END CODE */
-